﻿/* PRQA S 3108++ */
/**
 * Copyright (C) 2024 Isoft Infrastructure Software Co., Ltd.
 * SPDX-License-Identifier: LGPL-2.1-only-with-exception OR  LicenseRef-Commercial-License
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; version 2.1.
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this library;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 * or see <https://www.gnu.org/licenses/>.
 *
 * Alternatively, this file may be used under the terms of the Isoft Infrastructure Software Co., Ltd.
 * Commercial License, in which case the provisions of the Isoft Infrastructure Software Co., Ltd.
 * Commercial License shall apply instead of those of the GNU Lesser General Public License.
 *
 * You should have received a copy of the Isoft Infrastructure Software Co., Ltd.  Commercial License
 * along with this program. If not, please find it at <https://EasyXMen.com/xy/reference/permissions.html>
 *
 ********************************************************************************
 **                                                                            **
 **  FILENAME    : sm2.h                                                       **
 **                                                                            **
 **  Created on  :                                                             **
 **  Author      : For the world peace                                         **
 **  Vendor      :                                                             **
 **  DESCRIPTION : implementation header for sm2                               **
 **                                                                            **
 **  SPECIFICATION(S) :   AUTOSAR classic Platform 4.4.0                       **
 **                                                                            **
 *******************************************************************************/
/* PRQA S 3108-- */
#ifndef PEACE_SM2_H
#define PEACE_SM2_H
/*******************************************************************************
**                      Includes                                              **
*******************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "sm2_common.h"
#include "istd_lib.h"
/*******************************************************************************
**                      Global Symbols                                        **
*******************************************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
/**
 * @brief Minimum plaintext size for SM2 operations.
 *
 * This macro defines the minimum size of the plaintext that can be processed by SM2 functions.
 */
#define peace_sm2_MIN_PLAINTEXT_SIZE 1
/**
 * @brief Defines the size of the big number (BN) structure.
 *
 * This macro defines the size of the `peace_sm2_BN` structure.
 */
#define PEACE_SM2_sizeof_bn (sizeof(peace_sm2_BN))
/**
 * @brief Maximum plaintext size for SM2 operations.
 *
 * This macro defines the maximum size of the plaintext that can be processed by SM2 functions.
 */
#define peace_sm2_MAX_PLAINTEXT_SIZE 255
/**
 * @brief Copy a Jacobian point.
 *
 * This macro copies the contents of one Jacobian point to another.
 *
 * @param R Destination Jacobian point.
 * @param P Source Jacobian point.
 */
#define PEACE_SM2_jacobian_point_copy(R, P) memcpy((R), (P), sizeof(peace_sm2_JACOBIAN_POINT))

/**
 * @brief Default ID for SM2 operations.
 */
#define PEACE_SM2_DEFAULT_ID "1234567812345678"

/**
 * @brief Length of the default ID used in SM2 operations.
 */
#define PEACE_SM2_DEFAULT_ID_LENGTH (sizeof(PEACE_SM2_DEFAULT_ID) - 1)

/**
 * @brief Bit length of the default ID used in SM2 operations.
 */
#define PEACE_SM2_DEFAULT_ID_BITS (PEACE_SM2_DEFAULT_ID_LENGTH * 8)

/**
 * @brief Maximum bit length of the ID used in SM2 operations.
 */
#define PEACE_SM2_MAX_ID_BITS 65535

/**
 * @brief Maximum byte length of the ID used in SM2 operations.
 */
#define PEACE_SM2_MAX_ID_LENGTH (PEACE_SM2_MAX_ID_BITS / 8)

/*******************************************************************************
**                      Global Data Types                                     **
*******************************************************************************/
/**
 * @brief Type definition for a big number (BN).
 *
 * This type represents a big number used in SM2 operations.
 */
typedef uint64_t peace_sm2_BN[8];

extern const peace_sm2_BN peace_sm2_N;
extern const peace_sm2_BN peace_sm2_ONE;

/**
 * @brief Standard return type for functions.
 *
 * This type is used as the standard return type for functions, where E_OK indicates success and E_NOT_OK indicates failure.
 */
typedef uint8 Std_ReturnType;

/**
 * @brief Type definition for a field element over Fp.
 *
 * This type represents a field element over Fp used in SM2 operations.
 */
typedef peace_sm2_BN peace_sm2_Fp;

/**
 * @brief Type definition for a field element over Fn.
 *
 * This type represents a field element over Fn used in SM2 operations.
 */
typedef peace_sm2_BN peace_sm2_Fn;

/**
 * @brief Structure representing a Jacobian point.
 *
 * This structure holds the coordinates of a point in Jacobian form used in elliptic curve operations.
 */
typedef struct
{
	peace_sm2_BN X; /**< X coordinate of the Jacobian point. */
	peace_sm2_BN Y; /**< Y coordinate of the Jacobian point. */
	peace_sm2_BN Z; /**< Z coordinate of the Jacobian point. */
} peace_sm2_JACOBIAN_POINT;

/**
 * @brief Type definition for a big number represented as a byte array.
 *
 * This type represents a big number as a byte array of fixed length.
 */
typedef uint8 peace_sm2_bn_t[32];

/**
 * @brief Structure representing an affine point.
 *
 * This structure holds the coordinates of a point in affine form used in elliptic curve operations.
 */
typedef struct
{
	uint8 x[32]; /**< X coordinate of the affine point. */
	uint8 y[32]; /**< Y coordinate of the affine point. */
} peace_sm2_POINT;

/**
 * @brief Structure representing an SM2 key pair.
 *
 * This structure holds both the public and private keys for SM2 operations.
 */
typedef struct
{
	peace_sm2_POINT public_key; /**< Public key in affine form. */
	uint8 private_key[32];		/**< Private key as a byte array. */
} peace_sm2_KEY;

/**
 * @brief Structure representing an SM2 signature.
 *
 * This structure holds the components of an SM2 signature.
 */
typedef struct
{
	uint8 r[32]; /**< R component of the signature. */
	uint8 s[32]; /**< S component of the signature. */
} peace_sm2_SIGNATURE;

/**
 * @brief Enumerations for different sizes of SM2 signatures.
 *
 * These enumerations define the possible sizes of SM2 signatures.
 */
enum
{
	peace_sm2_signature_compact_size = 70, /**< Compact size of the signature. */
	peace_sm2_signature_typical_size = 71, /**< Typical size of the signature. */
	peace_sm2_signature_max_size = 72	   /**< Maximum size of the signature. */
};

/**
 * @brief Structure representing the context for SM2 signing.
 *
 * This structure holds the context information required for SM2 signing operations.
 */
typedef struct
{
	peace_sm3_CTX peace_sm3_ctx; /**< Context for SM3 hashing. */
	peace_sm2_KEY key;			 /**< SM2 key pair. */
} peace_sm2_SIGN_CTX;
	/**
	 * @brief Structure representing an SM2 ciphertext.
	 *
	 * This structure holds the encrypted message along with its associated metadata.
	 */
	typedef struct
	{
		peace_sm2_POINT point;							  /**< Affine point used in encryption. */
		uint8_t hash[32];								  /**< Hash of the plaintext. */
		uint8_t ciphertext_size;						  /**< Size of the ciphertext. */
		uint8_t ciphertext[peace_sm2_MAX_PLAINTEXT_SIZE]; /**< Ciphertext data. */
	} peace_sm2_CIPHERTEXT;
/**
 * @brief Enumerations for different sizes of SM2 ciphertext points.
 *
 * These enumerations define the possible sizes of the affine points used in SM2 ciphertexts.
 */
enum
{
	peace_sm2_ciphertext_compact_point_size = 68, /**< Compact size of the ciphertext point. */
	peace_sm2_ciphertext_typical_point_size = 69, /**< Typical size of the ciphertext point. */
	peace_sm2_ciphertext_max_point_size = 70	  /**< Maximum size of the ciphertext point. */
};

/*******************************************************************************
**                      Global Data                                           **
*******************************************************************************/

/*******************************************************************************
**                      Global Functions                                      **
*******************************************************************************/

/**
 * @brief Verifies an SM2 signature.
 *
 * This function verifies an SM2 signature using the provided buffer, private key, public key, and signature.
 *
 * @param[in] buf Pointer to the buffer containing the data to be verified.
 * @param[in] bufLength Length of the buffer.
 * @param[in] privateKey Pointer to the private key.
 * @param[in] publicKey Pointer to the public key.
 * @param[out] sigVerifyResult Pointer to the result of the signature verification.
 * @param[in] sigLen Length of the signature.
 * @return Std_ReturnType Returns E_OK on success, E_NOT_OK on failure.
 */
Std_ReturnType peace_sm2_verify(const uint8 *buf, uint32 bufLength, uint8 *privateKey, uint8 *publicKey, const uint8 *sigResult, uint32 sigLen);

/**
 * @brief Signs a buffer using the SM2 algorithm.
 *
 * This function signs the provided buffer using the SM2 algorithm with the given private key and public key.
 *
 * @param[in] buf Pointer to the buffer containing the data to be signed.
 * @param[in] buf_length Length of the buffer.
 * @param[in] Private_Key Pointer to the private key.
 * @param[in] Publickey Pointer to the public key.
 * @param[out] Sig_Result Pointer to the result of the signing operation.
 * @param[out] Sig_R Pointer to the R component of the signature.
 * @param[out] Sig_S Pointer to the S component of the signature.
 * @param[out] siglen Pointer to the length of the signature.
 * @return Std_ReturnType Returns E_OK on success, E_NOT_OK on failure.
 */
Std_ReturnType peace_sm2_sign(const uint8 *buf, uint32 buf_length, uint8 *Private_Key, uint8 *Publickey, uint8 *Sig_Result, uint8 *Sig_R, uint8 *Sig_S, uint32 *siglen);

/**
 * @brief Checks if the given big number is zero.
 *
 * This function iterates through each byte of the big number to determine if all bytes are zero.
 *
 * @param[in] a Pointer to the big number represented as an array of 8 bytes.
 *
 * @return
 * - 0 if the big number is not zero.
 * - 1 if the big number is zero.
 *
 * @details
 * The function performs a straightforward check by iterating over each element of the array.
 * If any element is non-zero, it immediately returns 0. If all elements are zero, it returns 1.
 * This is a critical check in cryptographic operations to avoid potential side-channel attacks.
 */
static inline int peace_sm2_bn_is_zero(const peace_sm2_BN a)
{
    uint8 i;
    for (i = 0; i < 8; i++)
    {
        if (a[i] != 0)
            return 0;
    }
    return 1;
}

/**
 * @brief Checks if the given big number is equal to one.
 *
 * This function checks whether the provided big number is equal to one by examining its internal representation.
 * The big number is represented as an array of 8 bytes.
 * The function returns 1 if the big number is one, otherwise it returns 0.
 *
 * @param[in] a Pointer to the big number array of type peace_sm2_BN.
 * @return 1 if the big number is one, 0 otherwise.
 */
static inline int peace_sm2_bn_is_one(const peace_sm2_BN a)
{
    uint8 i;
    if (a[0] != 1)
        return 0;
    for (i = 1; i < 8; i++)
    {
        if (a[i] != 0)
            return 0;
    }
    return 1;
}

/**
 * @brief Checks if a big number is odd.
 *
 * This function checks if the given big number `a` is odd.
 *
 * @param[in] a   Big number to check.
 * @return Non-zero if `a` is odd, zero otherwise.
 */
static inline int peace_sm2_bn_is_odd(const peace_sm2_BN a)
{
    return a[0] & 0x01;
}


/**
 * @brief Compares two big numbers.
 *
 * This function compares two big numbers `a` and `b`.
 *
 * @param[in] a   First big number.
 * @param[in] b   Second big number.
 * @return 1 if `a` is greater than `b`, E_ERROR if `a` is less than `b`, 0 if they are equal.
 */
 static inline int peace_sm2_bn_cmp(const peace_sm2_BN a, const peace_sm2_BN b)
{
    int i;
    for (i = 7; i >= 0; i--)
    {
        if (a[i] > b[i])
            return 1;
        if (a[i] < b[i])
            return E_ERROR;
    }
    return 0;
}

/**
 * @brief Subtracts two big numbers.
 *
 * This function subtracts big number `b` from `a` and stores the result in `ret`.
 *
 * @param[out] ret Resulting big number.
 * @param[in] a   First big number.
 * @param[in] b   Second big number.
 */
static inline void peace_sm2_bn_sub(peace_sm2_BN ret, const peace_sm2_BN a, const peace_sm2_BN b)
{
    uint8 i;
    // peace_sm2_BN r;
    ret[0] = ((uint64_t)1 << 32) + a[0] - b[0];
    for (i = 1; i < 7; i++)
    {
        ret[i] = (uint64_t)(0xffffffffu + a[i]+ (uint64_t)((ret[i - 1] >> 32)&0xffffffffu) - b[i]) ;
        ret[i - 1] &= 0xffffffffu;
    }
    ret[i] = (uint64_t)(a[i]+ (uint64_t)((ret[i - 1] >> 32)&0xffffffffu) - b[i]  - 1);
    ret[i - 1] &= 0xffffffffu;
    //(void)ILib_memcpy(ret, r, PEACE_SM2_sizeof_bn);
}
/**
 * @brief Adds two big numbers.
 *
 * This function adds two big numbers `a` and `b` and stores the result in `r`.
 *
 * @param[out] r  Resulting big number.
 * @param[in] a   First big number.
 * @param[in] b   Second big number.
 */
static inline void peace_sm2_bn_add(peace_sm2_BN r, const peace_sm2_BN a, const peace_sm2_BN b)
{
    uint8 i;
    r[0] = a[0] + b[0];

    for (i = 1; i < 8; i++)
    {
        r[i] = a[i] + b[i] + (uint32_t)(r[i - 1] >> 32);
    }
    for (i = 0; i < 7; i++)
    {
        r[i] &= 0xffffffffu;
    }
}
/**
 * @brief Sets a big number to a word value.
 *
 * This function sets the given big number `r` to the specified word value `a`.
 *
 * @param[out] r  Big number to set.
 * @param[in] a   Word value to set.
 */
static inline void peace_sm2_bn_set_word(peace_sm2_BN r, uint32 a)
{
    uint8 i;
    r[0] = a;
    for (i = 1; i < 8; i++)
    {
        r[i] = 0;
    }
}
/**
 * @brief Converts an ASN.1 integer to a big number.
 *
 * This function converts an ASN.1 integer to a big number.
 *
 * @param[out] r Resultant big number.
 * @param[in] d Pointer to the ASN.1 integer data.
 * @param[in] dlen Length of the ASN.1 integer data.
 * @return int Returns 0 on success, non-zero on failure.
 */
int peace_sm2_bn_from_asn1_integer(peace_sm2_BN r, const uint8 *d, uint32 dlen);

/**
 * @brief Prints a big number to a file.
 *
 * This function prints a big number to a file with the specified format and indentation.
 *
 * @param[in] fp File pointer.
 * @param[in] fmt Format specifier.
 * @param[in] ind Indentation level.
 * @param[in] label Label for the big number.
 * @param[in] a Big number to print.
 * @return int Returns 0 on success, non-zero on failure.
 */
int peace_sm2_bn_print(FILE *fp, int fmt, int ind, const char *label, const peace_sm2_BN a);

/**
 * @brief Performs a right shift on a big number.
 *
 * This function performs a right shift on a big number by the specified number of bits.
 *
 * @param[out] ret Resultant big number after the right shift.
 * @param[in] a Big number to be shifted.
 * @param[in] nbits Number of bits to shift.
 * @return int Returns 0 on success, non-zero on failure.
 */
int peace_sm2_bn_rshift(peace_sm2_BN ret, const peace_sm2_BN a, unsigned int nbits);

/**
 * @brief Converts a big number to a byte array.
 *
 * This function converts a big number to a byte array of fixed length.
 *
 * @param[in] a Big number to convert.
 * @param[out] out Byte array to store the result.
 */
void peace_sm2_bn_to_bytes(const peace_sm2_BN a, uint8 out[32]);

/**
 * @brief Converts a byte array to a big number.
 *
 * This function converts the given 32-byte array `in` into a big number `r`.
 * The conversion is done in big-endian order.
 *
 * @param[out] r  Big number to store the result.
 * @param[in] in  Input byte array of length 32.
 */
static inline void peace_sm2_bn_from_bytes(peace_sm2_BN r, const uint8 in[32])
{
    int i;
    for (i = 7; i >= 0; i--)
    {
        r[i] = GETU32(in);
        in += sizeof(uint32);
    }
}

/**
 * @brief Converts a big number to a bit string.
 *
 * This function converts a big number to a bit string.
 *
 * @param[in] a Big number to convert.
 * @param[out] bits Bit string to store the result.
 */
void peace_sm2_bn_to_bits(const peace_sm2_BN a, char bits[256]);

/**
 * @brief Sets a big number to a word value.
 *
 * This function sets a big number to a specified word value.
 *
 * @param[out] r Resultant big number.
 * @param[in] a Word value to set.
 */
void peace_sm2_bn_set_word(peace_sm2_BN r, uint32 a);

/**
 * @brief Adds two big numbers.
 *
 * This function adds two big numbers.
 *
 * @param[out] r Resultant big number after addition.
 * @param[in] a First big number.
 * @param[in] b Second big number.
 */
void peace_sm2_bn_add(peace_sm2_BN r, const peace_sm2_BN a, const peace_sm2_BN b);

/**
 * @brief Subtracts two big numbers.
 *
 * This function subtracts big number `b` from `a` and stores the result in `ret`.
 *
 * @param[out] ret Resulting big number.
 * @param[in] a   First big number.
 * @param[in] b   Second big number.
 */
//void peace_sm2_bn_sub(peace_sm2_BN ret, const peace_sm2_BN a, const peace_sm2_BN b);

/**
 * @brief Generates a random big number within a specified range.
 *
 * This function generates a random big number within the specified range.
 *
 * @param[out] r Resultant random big number.
 * @param[in] range Upper bound of the range.
 * @return int Returns 0 on success, non-zero on failure.
 */
int peace_sm2_bn_rand_range(peace_sm2_BN r, const peace_sm2_BN range);


/**
 * @brief Subtracts one field element from another in Fp.
 *
 * This function performs the subtraction of the second field element from the first in the finite field Fp.
 *
 * @param[out] r Resultant field element after subtraction.
 * @param[in] a First field element.
 * @param[in] b Second field element.
 */
void peace_sm2_fp_sub(peace_sm2_Fp r, const peace_sm2_Fp a, const peace_sm2_Fp b);

/**
 * @brief Multiplies two field elements in Fp.
 *
 * This function performs the multiplication of two field elements in the finite field Fp.
 *
 * @param[out] r Resultant field element after multiplication.
 * @param[in] a First field element.
 * @param[in] b Second field element.
 */
void peace_sm2_fp_mul(peace_sm2_Fp r, const peace_sm2_Fp a, const peace_sm2_Fp b);




/**
 * @brief Divides a field element by 2 in Fp.
 *
 * This function divides the specified field element by 2 in the finite field Fp.
 *
 * @param[out] r Resultant field element after division by 2.
 * @param[in] a Field element to be divided.
 */
void peace_sm2_fp_div2(peace_sm2_Fp r, const peace_sm2_Fp a);

/**
 * @brief Negates a field element in Fp.
 *
 * This function negates the specified field element in the finite field Fp.
 *
 * @param[out] r Resultant field element after negation.
 * @param[in] a Field element to be negated.
 */
void peace_sm2_fp_neg(peace_sm2_Fp r, const peace_sm2_Fp a);



/**
 * @brief Inverts a field element in Fp.
 *
 * This function computes the multiplicative inverse of the specified field element in the finite field Fp.
 *
 * @param[out] r Resultant field element after inversion.
 * @param[in] a Field element to be inverted.
 */
void peace_sm2_fp_inv(peace_sm2_Fp r, const peace_sm2_Fp a);

/**
 * @brief Subtracts one field element from another in Fn.
 *
 * This function performs the subtraction of the second field element from the first in the finite field Fn.
 *
 * @param[out] r Resultant field element after subtraction.
 * @param[in] a First field element.
 * @param[in] b Second field element.
 */
void peace_sm2_fn_sub(peace_sm2_Fn r, const peace_sm2_Fn a, const peace_sm2_Fn b);

/**
 * @brief Multiplies two field elements in Fn.
 *
 * This function performs the multiplication of two field elements in the finite field Fn.
 *
 * @param[out] r Resultant field element after multiplication.
 * @param[in] a First field element.
 * @param[in] b Second field element.
 */
void peace_sm2_fn_mul(peace_sm2_Fn r, const peace_sm2_Fn a, const peace_sm2_Fn b);

/**
 * @brief Exponentiates a field element in Fn.
 *
 * This function raises a field element to the power of another field element in the finite field Fn.
 *
 * @param[out] r Resultant field element after exponentiation.
 * @param[in] a Base field element.
 * @param[in] e Exponent field element.
 */
void peace_sm2_fn_exp(peace_sm2_Fn r, const peace_sm2_Fn a, const peace_sm2_Fn e);


/**
 * @brief Inverts a field element in Fn.
 *
 * This function computes the multiplicative inverse of the specified field element in the finite field Fn.
 *
 * @param[out] r Resultant field element after inversion.
 * @param[in] a Field element to be inverted.
 */
void peace_sm2_fn_inv(peace_sm2_Fn r, const peace_sm2_Fn a);

/**
 * @brief Generates a random field element in Fn.
 *
 * This function generates a random field element in the finite field Fn.
 *
 * @param[out] r Randomly generated field element.
 * @return int Returns 0 on success, non-zero on failure.
 */
int peace_sm2_fn_rand(peace_sm2_BN r);

/**
 * @brief Retrieves the X and Y coordinates of a Jacobian point.
 *
 * This function retrieves the X and Y coordinates from the specified Jacobian point.
 *
 * @param[in] P Pointer to the Jacobian point from which coordinates will be retrieved.
 * @param[out] x Buffer to store the X coordinate as a big number.
 * @param[out] y Buffer to store the Y coordinate as a big number.
 */
void peace_sm2_jacobian_point_get_xy(const peace_sm2_JACOBIAN_POINT *P, peace_sm2_BN x, peace_sm2_BN y);


/**
 * @brief Doubles a Jacobian point.
 *
 * This function computes the doubling of the specified Jacobian point.
 *
 * @param[out] R Pointer to the Jacobian point that will store the result.
 * @param[in] P Pointer to the Jacobian point to be doubled.
 */
void peace_sm2_jacobian_point_dbl(peace_sm2_JACOBIAN_POINT *R, const peace_sm2_JACOBIAN_POINT *P);

/**
 * @brief Adds two Jacobian points.
 *
 * This function computes the addition of two specified Jacobian points.
 *
 * @param[out] R Pointer to the Jacobian point that will store the result.
 * @param[in] P Pointer to the first Jacobian point.
 * @param[in] Q Pointer to the second Jacobian point.
 */
void peace_sm2_jacobian_point_add(peace_sm2_JACOBIAN_POINT *R, const peace_sm2_JACOBIAN_POINT *P, const peace_sm2_JACOBIAN_POINT *Q);


/**
 * @brief Multiplies a Jacobian point by a scalar.
 *
 * This function multiplies the specified Jacobian point by a scalar value.
 *
 * @param[out] R Pointer to the Jacobian point that will store the result.
 * @param[in] k Scalar value as a big number.
 * @param[in] P Pointer to the Jacobian point to be multiplied.
 */
void peace_sm2_jacobian_point_mul(peace_sm2_JACOBIAN_POINT *R, const peace_sm2_BN k, const peace_sm2_JACOBIAN_POINT *P);

/**
 * @brief Converts a Jacobian point to a byte array.
 *
 * This function converts the specified Jacobian point to a byte array representation.
 *
 * @param[in] P Pointer to the Jacobian point to be converted.
 * @param[out] out Buffer to store the byte array representation (64 bytes).
 */
void peace_sm2_jacobian_point_to_bytes(const peace_sm2_JACOBIAN_POINT *P, uint8 out[64]);

/**
 * @brief Converts a byte array to a Jacobian point.
 *
 * This function converts a byte array representation to a Jacobian point.
 *
 * @param[out] P Pointer to the Jacobian point that will store the result.
 * @param[in] in Byte array representation (64 bytes) of the Jacobian point.
 */
void peace_sm2_jacobian_point_from_bytes(peace_sm2_JACOBIAN_POINT *P, const uint8 in[64]);

/**
 * @brief Multiplies the generator point by a scalar.
 *
 * This function multiplies the generator point by a scalar value.
 *
 * @param[out] R Pointer to the Jacobian point that will store the result.
 * @param[in] k Scalar value as a big number.
 */
void peace_sm2_jacobian_point_mul_generator(peace_sm2_JACOBIAN_POINT *R, const peace_sm2_BN k);

/**
 * @brief Computes a linear combination of two Jacobian points.
 *
 * This function computes the result of t*P + s*G, where G is the generator point.
 *
 * @param[out] R Pointer to the Jacobian point that will store the result.
 * @param[in] t Scalar multiplier for point P as a big number.
 * @param[in] P Pointer to the first Jacobian point.
 * @param[in] s Scalar multiplier for the generator point as a big number.
 */
void peace_sm2_jacobian_point_mul_sum(peace_sm2_JACOBIAN_POINT *R, const peace_sm2_BN t, const peace_sm2_JACOBIAN_POINT *P, const peace_sm2_BN s);



/**
 * @brief Checks if a Jacobian point lies on the curve.
 *
 * This function checks whether the specified Jacobian point satisfies the equation of the elliptic curve.
 *
 * @param[in] P Pointer to the Jacobian point.
 * @return int Returns 1 if the point is on the curve, otherwise returns 0.
 */
int peace_sm2_jacobian_point_is_on_curve(const peace_sm2_JACOBIAN_POINT *P);

/**
 * @brief Prints a Jacobian point.
 *
 * This function prints the details of the specified Jacobian point to the file stream.
 *
 * @param[in] fp File pointer where the output will be written.
 * @param[in] fmt Format specifier for printing.
 * @param[in] ind Indentation level for formatting.
 * @param[in] label Label to prepend to the printed information.
 * @param[in] P Pointer to the Jacobian point.
 * @return int Number of characters printed.
 */
int peace_sm2_jacobian_point_print(FILE *fp, int fmt, int ind, const char *label, const peace_sm2_JACOBIAN_POINT *P);

	/**
	 * @brief Check if an elliptic curve point is on the curve.
	 *
	 * This function checks if the provided elliptic curve point lies on the curve.
	 *
	 * @param P Pointer to the elliptic curve point.
	 * @return int 1 if the point is on the curve, 0 otherwise.
	 */
	int peace_sm2_point_is_on_curve(const peace_sm2_POINT *P);
/**
 * @brief Print elliptic curve point.
 *
 * This function prints the elliptic curve point in the specified format and indentation level.
 *
 * @param fp File pointer where the output will be written.
 * @param fmt Format specifier.
 * @param ind Indentation level.
 * @param label Label to print before the point.
 * @param P Pointer to the elliptic curve point.
 * @return int Number of characters printed on success, -1 on failure.
 */
int peace_sm2_point_print(FILE *fp, int fmt, int ind, const char *label, const peace_sm2_POINT *P);

/**
 * @brief Sign a message digest using the SM2 algorithm.
 *
 * This function signs the provided message digest using the given SM2 private key and stores the signature in the specified structure.
 *
 * @param key Pointer to the SM2 private key.
 * @param dgst Pointer to the 32-byte message digest to be signed.
 * @param sig Pointer to the structure where the signature will be stored.
 * @return int 1 on success, 0 on failure.
 */
int peace_sm2_do_sign(const peace_sm2_KEY *key, const uint8 dgst[32], peace_sm2_SIGNATURE *sig);

/**
 * @brief Verify a message digest signature using the SM2 algorithm.
 *
 * This function verifies the provided message digest signature using the given SM2 public key.
 *
 * @param key Pointer to the SM2 public key.
 * @param dgst Pointer to the 32-byte message digest that was signed.
 * @param sig Pointer to the signature to be verified.
 * @return int 1 if the signature is valid, 0 if the signature is invalid or an error occurred.
 */
int peace_sm2_do_verify(const peace_sm2_KEY *key, const uint8 dgst[32], const peace_sm2_SIGNATURE *sig);

/**
 * @brief Convert SM2 signature to DER format.
 *
 * This function converts the SM2 signature to DER format and stores it in the specified buffer.
 *
 * @param sig Pointer to the SM2 signature.
 * @param out Pointer to the pointer that will receive the allocated buffer containing the DER-encoded signature.
 * @param outlen Pointer to the variable that will store the length of the DER-encoded signature.
 * @return int 1 on success, 0 on failure.
 */
int peace_sm2_signature_to_der(const peace_sm2_SIGNATURE *sig, uint8 **out, uint32 *outlen);

/**
 * @brief Convert DER-formatted SM2 signature to internal representation.
 *
 * This function converts the DER-formatted SM2 signature to the internal representation and stores it in the specified structure.
 *
 * @param sig Pointer to the SM2 signature structure where the result will be stored.
 * @param in Pointer to the pointer that points to the DER-encoded signature.
 * @param inlen Pointer to the variable that contains the length of the DER-encoded signature.
 * @return int 1 on success, 0 on failure.
 */
int peace_sm2_signature_from_der(peace_sm2_SIGNATURE *sig, const uint8 **in, uint32 *inlen);

/**
 * @brief Print SM2 signature.
 *
 * This function prints the SM2 signature in the specified format and indentation level.
 *
 * @param fp File pointer where the output will be written.
 * @param fmt Format specifier.
 * @param ind Indentation level.
 * @param label Label to print before the signature.
 * @param sig Pointer to the signature data.
 * @param siglen Length of the signature data.
 * @return int Number of characters printed on success, -1 on failure.
 */
int peace_sm2_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8 *sig, uint32 siglen);

/**
 * @brief Internal function to sign a message digest using the SM2 algorithm.
 *
 * This function internally signs the provided message digest using the given SM2 private key and stores the signature components in the specified buffers.
 *
 * @param key Pointer to the SM2 private key.
 * @param dgst Pointer to the 32-byte message digest to be signed.
 * @param sigbuf Pointer to the buffer where the complete signature will be stored.
 * @param sign_R Pointer to the buffer where the R component of the signature will be stored.
 * @param sign_S Pointer to the buffer where the S component of the signature will be stored.
 * @param siglen Pointer to the variable that will store the length of the signature.
 * @return int 1 on success, 0 on failure.
 */
int peace_sm2_sign_internal(const peace_sm2_KEY *key, const uint8 dgst[32], uint8 *sigbuf, uint8 *sign_R, uint8 *sign_S, uint32 *siglen);

/**
 * @brief Internal function to verify a message digest signature using the SM2 algorithm.
 *
 * This function internally verifies the provided message digest signature using the given SM2 public key.
 *
 * @param key Pointer to the SM2 public key.
 * @param dgst Pointer to the 32-byte message digest that was signed.
 * @param sig Pointer to the signature to be verified.
 * @param siglen Length of the signature.
 * @return int 1 if the signature is valid, 0 if the signature is invalid or an error occurred.
 */
int peace_sm2_verify_internal(const peace_sm2_KEY *key, const uint8 dgst[32], const uint8 *sig, uint32 siglen);

/**
 * @brief Compute the Z value for SM2.
 *
 * This function computes the Z value used in the SM2 algorithm based on the public key and the user ID.
 *
 * @param z Pointer to the output buffer where the computed Z value will be stored.
 * @param pub Pointer to the public key.
 * @param id Pointer to the user ID string.
 * @param idlen Length of the user ID string.
 * @return int 1 on success, 0 on failure.
 */
int sm2ComputeZ(uint8 z[32], const peace_sm2_POINT *pub, const char *id, uint32 idlen);

/**
 * @brief Initialize the SM2 signing context.
 *
 * This function initializes the SM2 signing context with the provided key and user ID.
 *
 * @param ctx Pointer to the SM2 signing context to initialize.
 * @param key Pointer to the SM2 key.
 * @param id Pointer to the user ID string.
 * @param idlen Length of the user ID string.
 * @return Std_ReturnType Standard return type indicating success or failure.
 */
Std_ReturnType peace_sm2_sign_init(peace_sm2_SIGN_CTX *ctx, const peace_sm2_KEY *key, const char *id, uint32 idlen);

/**
 * @brief Update the SM2 signing context with data.
 *
 * This function updates the SM2 signing context with the provided data.
 *
 * @param ctx Pointer to the SM2 signing context.
 * @param data Pointer to the data to update the context with.
 * @param datalen Length of the data.
 * @return Std_ReturnType Standard return type indicating success or failure.
 */
Std_ReturnType peace_sm2_sign_update(peace_sm2_SIGN_CTX *ctx, const uint8 *data, uint32 datalen);

/**
 * @brief Finalize the SM2 signing process.
 *
 * This function finalizes the SM2 signing process and produces the signature.
 *
 * @param ctx Pointer to the SM2 signing context.
 * @param sig Pointer to the output buffer where the signature will be stored.
 * @param Sig_R Pointer to the R component of the signature.
 * @param Sig_S Pointer to the S component of the signature.
 * @param siglen Pointer to the variable that will store the length of the signature.
 * @return Std_ReturnType Standard return type indicating success or failure.
 */
Std_ReturnType peace_sm2_sign_finish(peace_sm2_SIGN_CTX *ctx, uint8 *sig, uint8 *Sig_R, uint8 *Sig_S, uint32 *siglen);

/**
 * @brief Initialize the SM2 verification context.
 *
 * This function initializes the SM2 verification context with the provided key and user ID.
 *
 * @param ctx Pointer to the SM2 verification context to initialize.
 * @param key Pointer to the SM2 key.
 * @param id Pointer to the user ID string.
 * @param idlen Length of the user ID string.
 * @return int 1 on success, 0 on failure.
 */
int peace_sm2_verify_init(peace_sm2_SIGN_CTX *ctx, const peace_sm2_KEY *key, const char *id, uint32 idlen);

/**
 * @brief Update the SM2 verification context with data.
 *
 * This function updates the SM2 verification context with the provided data.
 *
 * @param ctx Pointer to the SM2 verification context.
 * @param data Pointer to the data to update the context with.
 * @param datalen Length of the data.
 * @return int 1 on success, 0 on failure.
 */
int peace_sm2_verify_update(peace_sm2_SIGN_CTX *ctx, const uint8 *data, uint32 datalen);

/**
 * @brief Finalize the SM2 verification process.
 *
 * This function finalizes the SM2 verification process and verifies the signature.
 *
 * @param ctx Pointer to the SM2 verification context.
 * @param sig Pointer to the signature to verify.
 * @param siglen Length of the signature.
 * @return int 1 if the signature is valid, 0 if invalid.
 */
int peace_sm2_verify_finish(peace_sm2_SIGN_CTX *ctx, const uint8 *sig, uint32 siglen);

	/**
	 * @brief Encrypt data using the SM2 algorithm (convenience wrapper).
	 *
	 * This function encrypts the input data using the provided SM2 key and stores the ciphertext in the specified buffer.
	 *
	 * @param key Pointer to the SM2 key.
	 * @param in Pointer to the input data to be encrypted.
	 * @param inlen Length of the input data.
	 * @param out Pointer to the buffer where the ciphertext will be stored.
	 * @param outlen Pointer to the variable that will store the length of the ciphertext.
	 * @return int 1 on success, 0 on failure.
	 */
	int peace_sm2_encrypt(const peace_sm2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);

	/**
	 * @brief Decrypt data using the SM2 algorithm (convenience wrapper).
	 *
	 * This function decrypts the ciphertext using the provided SM2 key and stores the plaintext in the specified buffer.
	 *
	 * @param key Pointer to the SM2 key.
	 * @param in Pointer to the ciphertext to be decrypted.
	 * @param inlen Length of the ciphertext.
	 * @param out Pointer to the buffer where the plaintext will be stored.
	 * @param outlen Pointer to the variable that will store the length of the plaintext.
	 * @return int 1 on success, 0 on failure.
	 */
	int peace_sm2_decrypt(const peace_sm2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
#ifdef __cplusplus
}
#endif
#endif
